﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Excel = Microsoft.Office.Interop.Excel;
using DimensionData.Data2;
using System.Diagnostics;

namespace DimensionAddIn
{
    public class DocumentRender
    {
        private Excel.Worksheet _worksheet;

        public DocumentRender(Excel.Worksheet worksheet)
        {
            _worksheet = worksheet;
        }

        public void RenderYDim(Excel.Worksheet worksheet, int ydCount, int firstRow, int beginCol, List<DRow> rows)
        {
            for (int rowIndex = 0; rowIndex < rows.Count; rowIndex++)
            {
                DRow dtRow = rows[rowIndex];

                for (int dIndex = 0; dIndex < ydCount; dIndex++)
                {
                    worksheet.XGetCell(firstRow + rowIndex, beginCol + dIndex).Value2 = dtRow.Items[dIndex].Name;
                    worksheet.XGetCell(firstRow + rowIndex, beginCol + dIndex).IndentLevel = dtRow.Items[dIndex].Level;
                    worksheet.XGetCell(firstRow + rowIndex, beginCol + dIndex).Interior.Color = 0xffcf9c;
                    worksheet.XGetCell(firstRow + rowIndex, beginCol + dIndex).Borders[Excel.XlBordersIndex.xlEdgeLeft].Weight = Excel.XlBorderWeight.xlThin;
                    worksheet.XGetCell(firstRow + rowIndex, beginCol + dIndex).Borders[Excel.XlBordersIndex.xlEdgeTop].Weight = Excel.XlBorderWeight.xlThin;
                    worksheet.XGetCell(firstRow + rowIndex, beginCol + dIndex).Borders[Excel.XlBordersIndex.xlEdgeRight].Weight = Excel.XlBorderWeight.xlThin;
                    worksheet.XGetCell(firstRow + rowIndex, beginCol + dIndex).Borders[Excel.XlBordersIndex.xlEdgeBottom].Weight = Excel.XlBorderWeight.xlThin;
                }
            }
        }

        public void RenderXDim(Excel.Worksheet worksheet, int xdCount, int firstCol, int beginRow, List<DRow> rows)
        {
            for (int rowIndex = 0; rowIndex < rows.Count; rowIndex++)
            {
                DRow dtRow = rows[rowIndex];

                for (int dIndex = 0; dIndex < xdCount; dIndex++)
                {
                    worksheet.XGetCell(beginRow + dIndex, firstCol + rowIndex).Value2 = dtRow.Items[dIndex].Name;

                    //sheet.XGetCell(beginRow + dIndex, firstCol + rowIndex).IndentLevel = dtRow.Items[dIndex].Level;

                    // set background
                    worksheet.XGetCell(beginRow + dIndex, firstCol + rowIndex).Interior.Color = 0xffcf9c;

                    //set border
                    worksheet.XGetCell(beginRow + dIndex, firstCol + rowIndex).Borders[Excel.XlBordersIndex.xlEdgeLeft].Weight = Excel.XlBorderWeight.xlThin;
                    worksheet.XGetCell(beginRow + dIndex, firstCol + rowIndex).Borders[Excel.XlBordersIndex.xlEdgeTop].Weight = Excel.XlBorderWeight.xlThin;
                    worksheet.XGetCell(beginRow + dIndex, firstCol + rowIndex).Borders[Excel.XlBordersIndex.xlEdgeRight].Weight = Excel.XlBorderWeight.xlThin;
                    worksheet.XGetCell(beginRow + dIndex, firstCol + rowIndex).Borders[Excel.XlBordersIndex.xlEdgeBottom].Weight = Excel.XlBorderWeight.xlThin;
                }
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="worksheet"></param>
        /// <param name="tables"></param>
        public void RenderPageDim(Excel.Worksheet worksheet, List<PageDim> tables)
        {
            for (int index = 0; index < tables.Count; index++)
            {
                DData table = tables[index].DimData;
                List<DRow> rows = table.Complanate2();

                worksheet.XGetCell(3, 2+ 2 * index).Value2 = table.Table.Name;
                Excel.Range selection = worksheet.XGetCell(3, 2 + 2 * index + 1);
                selection.Validation.Delete();

                string formula = string.Format("={0}dl!{1}{2}:{3}{4}", worksheet.Name, ToAA(index + 1), "1", ToAA(index + 1), rows.Count);
                selection.Validation.Add(
                    Excel.XlDVType.xlValidateList,
                    Excel.XlDVAlertStyle.xlValidAlertStop,
                    Type.Missing,
                    formula,
                    Type.Missing);
            }
        }

        public bool RenderDims(Excel.Workbook workbook, List<PageDim> trees)
        {
            bool isNewResult = false;
            //return;
            string dlSheetName = string.Format("{0}dl", _worksheet.Name);
            Excel.Worksheet sheet = null;

            foreach (var item in workbook.Sheets)
            {
                Excel.Worksheet iSheet = (Excel.Worksheet)item;
                if (iSheet.Name == dlSheetName)
                {
                    sheet = iSheet;
                    break;
                }
            }
            if (sheet == null)
            {
                isNewResult = true;
                sheet = workbook.Application.Sheets.Add();
                sheet.Visible = Excel.XlSheetVisibility.xlSheetVeryHidden;
                sheet.Name = dlSheetName;
            }
            else
            {
                sheet.UsedRange.Clear();
            }

            for (int index = 0; index < trees.Count; index++)
            {
                DData tree = trees[index].DimData;
                List<DRow> rows = tree.Complanate2();

                for (int rowIndex = 0; rowIndex < rows.Count; rowIndex++)
                {
                    sheet.XGetCell(rowIndex + 1, index + 1).Value2 = rows[rowIndex].Items[0].Name;
                }
            }
            return isNewResult;
        }

        public void RenderYDim(Excel.Worksheet worksheet, int ydCount, int firstRow, int beginCol, List<DRow> rows, int pdLevel, string pdName)
        {
            int aRowIndex = 0;
            for (int rowIndex = 0; rowIndex < rows.Count; rowIndex++)
            {
                DRow dtRow = rows[rowIndex];

                string cpdName = dtRow.Items[pdLevel].Name;
                if (cpdName == pdName)
                {
                    for (int dIndex = 0; dIndex < ydCount; dIndex++)
                    {
                        worksheet.XGetCell(firstRow + aRowIndex, beginCol + dIndex).Value2 = dtRow.Items[dIndex].Name;
                        worksheet.XGetCell(firstRow + aRowIndex, beginCol + dIndex).IndentLevel = dtRow.Items[dIndex].Level;
                        worksheet.XGetCell(firstRow + aRowIndex, beginCol + dIndex).Interior.Color = 0xffcf9c;
                        worksheet.XGetCell(firstRow + aRowIndex, beginCol + dIndex).Borders[Excel.XlBordersIndex.xlEdgeLeft].Weight = Excel.XlBorderWeight.xlThin;
                        worksheet.XGetCell(firstRow + aRowIndex, beginCol + dIndex).Borders[Excel.XlBordersIndex.xlEdgeTop].Weight = Excel.XlBorderWeight.xlThin;
                        worksheet.XGetCell(firstRow + aRowIndex, beginCol + dIndex).Borders[Excel.XlBordersIndex.xlEdgeRight].Weight = Excel.XlBorderWeight.xlThin;
                        worksheet.XGetCell(firstRow + aRowIndex, beginCol + dIndex).Borders[Excel.XlBordersIndex.xlEdgeBottom].Weight = Excel.XlBorderWeight.xlThin;
                    }
                    aRowIndex++;
                }
            }
        }

        public void RenderXDim(Excel.Worksheet worksheet, int xdCount, int firstCol, int beginRow, List<DRow> rows, int pdLevel, string pdName)
        {
            int aColIndex = 0;
            for (int rowIndex = 0; rowIndex < rows.Count; rowIndex++)
            {
                DRow dtRow = rows[rowIndex];
                
                string cpdName = dtRow.Items[pdLevel].Name;
                if (cpdName == pdName)
                {
                    for (int dIndex = 0; dIndex < xdCount; dIndex++)
                    {
                        worksheet.XGetCell(beginRow + dIndex, firstCol + aColIndex).Value2 = dtRow.Items[dIndex].Name;

                        //sheet.XGetCell(beginRow + dIndex, firstCol + rowIndex).IndentLevel = dtRow.Items[dIndex].Level;

                        // set background
                        worksheet.XGetCell(beginRow + dIndex, firstCol + aColIndex).Interior.Color = 0xffcf9c;

                        //set border
                        worksheet.XGetCell(beginRow + dIndex, firstCol + aColIndex).Borders[Excel.XlBordersIndex.xlEdgeLeft].Weight = Excel.XlBorderWeight.xlThin;
                        worksheet.XGetCell(beginRow + dIndex, firstCol + aColIndex).Borders[Excel.XlBordersIndex.xlEdgeTop].Weight = Excel.XlBorderWeight.xlThin;
                        worksheet.XGetCell(beginRow + dIndex, firstCol + aColIndex).Borders[Excel.XlBordersIndex.xlEdgeRight].Weight = Excel.XlBorderWeight.xlThin;
                        worksheet.XGetCell(beginRow + dIndex, firstCol + aColIndex).Borders[Excel.XlBordersIndex.xlEdgeBottom].Weight = Excel.XlBorderWeight.xlThin;
                    }
                    aColIndex++;
                }
            }
        }

        public void RenderYDim(Excel.Worksheet worksheet, int ydCount, int firstRow, int beginCol, List<DRow> rows, Dictionary<PageDim, string> pageDims)
        {
            int aRowIndex = 0;
            for (int rowIndex = 0; rowIndex < rows.Count; rowIndex++)
            {
                DRow dtRow = rows[rowIndex];

                bool isVisible = true;

                foreach (var pageDim in pageDims.Keys)
                {
                    string cpdName = dtRow.Items[pageDim.Index].Name;
                    if (cpdName != pageDims[pageDim])
                    {
                        isVisible = false;
                        break;
                    }
                }

                if (isVisible)
                {
                    for (int dIndex = 0; dIndex < ydCount; dIndex++)
                    {
                        worksheet.XGetCell(firstRow + aRowIndex, beginCol + dIndex).Value2 = dtRow.Items[dIndex].Name;
                        worksheet.XGetCell(firstRow + aRowIndex, beginCol + dIndex).IndentLevel = dtRow.Items[dIndex].Level;
                        worksheet.XGetCell(firstRow + aRowIndex, beginCol + dIndex).Interior.Color = 0xffcf9c;
                        worksheet.XGetCell(firstRow + aRowIndex, beginCol + dIndex).Borders[Excel.XlBordersIndex.xlEdgeLeft].Weight = Excel.XlBorderWeight.xlThin;
                        worksheet.XGetCell(firstRow + aRowIndex, beginCol + dIndex).Borders[Excel.XlBordersIndex.xlEdgeTop].Weight = Excel.XlBorderWeight.xlThin;
                        worksheet.XGetCell(firstRow + aRowIndex, beginCol + dIndex).Borders[Excel.XlBordersIndex.xlEdgeRight].Weight = Excel.XlBorderWeight.xlThin;
                        worksheet.XGetCell(firstRow + aRowIndex, beginCol + dIndex).Borders[Excel.XlBordersIndex.xlEdgeBottom].Weight = Excel.XlBorderWeight.xlThin;
                    }
                    aRowIndex++;
                }
            }
        }

        public void RenderXDim(Excel.Worksheet worksheet, int xdCount, int firstCol, int beginRow, List<DRow> rows, Dictionary<PageDim, string> pageDims)
        {
            int aColIndex = 0;
            for (int rowIndex = 0; rowIndex < rows.Count; rowIndex++)
            {
                DRow dtRow = rows[rowIndex];

                bool isVisible = true;

                foreach (var pageDim in pageDims.Keys)
                {
                    string cpdName = dtRow.Items[pageDim.Index].Name;
                    if (cpdName != pageDims[pageDim])
                    {
                        isVisible = false;
                        break;
                    }
                }

                if (isVisible)
                {
                    for (int dIndex = 0; dIndex < xdCount; dIndex++)
                    {
                        worksheet.XGetCell(beginRow + dIndex, firstCol + aColIndex).Value2 = dtRow.Items[dIndex].Name;

                        //sheet.XGetCell(beginRow + dIndex, firstCol + rowIndex).IndentLevel = dtRow.Items[dIndex].Level;

                        // set background
                        worksheet.XGetCell(beginRow + dIndex, firstCol + aColIndex).Interior.Color = 0xffcf9c;

                        //set border
                        worksheet.XGetCell(beginRow + dIndex, firstCol + aColIndex).Borders[Excel.XlBordersIndex.xlEdgeLeft].Weight = Excel.XlBorderWeight.xlThin;
                        worksheet.XGetCell(beginRow + dIndex, firstCol + aColIndex).Borders[Excel.XlBordersIndex.xlEdgeTop].Weight = Excel.XlBorderWeight.xlThin;
                        worksheet.XGetCell(beginRow + dIndex, firstCol + aColIndex).Borders[Excel.XlBordersIndex.xlEdgeRight].Weight = Excel.XlBorderWeight.xlThin;
                        worksheet.XGetCell(beginRow + dIndex, firstCol + aColIndex).Borders[Excel.XlBordersIndex.xlEdgeBottom].Weight = Excel.XlBorderWeight.xlThin;
                    }
                    aColIndex++;
                }
            }
        }
        /*
        public void RenderContent(DocDimData schema, DocData docMatrix)
        {
            DTree yTree = schema.YTree;
            DTree xTree = schema.XTree;
            List<PageDim> pageDims = schema.PageDims;

            int beginRow = 5;
            int firstRow = 5;
            int beginCol = 2;
            int firstCol = 2;

            int ydCount = yTree.Table.RelationChain.Relations.Count + 1;
            firstCol += yTree.Table.RelationChain.Relations.Count + 1;

            int xdCount = xTree.Table.RelationChain.Relations.Count + 1;
            firstRow += xTree.Table.RelationChain.Relations.Count + 1;

            List<DRow> yRows = yTree.Complanate2();
            List<DRow> xRows = xTree.Complanate2();

            List<int> visualYRows = new List<int>();
            List<int> visualXRows = new List<int>();
            #region 清除当前内容区域
            if(docMatrix.VisualRect.IsValid())
            {
                Debug.WriteLine("clear rect:{0},{1}-{2},{3}",
                    docMatrix.VisualRect.BeginRow, 
                    docMatrix.VisualRect.BeginCol,
                    docMatrix.VisualRect.EndRow, 
                    docMatrix.VisualRect.EndCol);
                Excel.Range ltCell = _worksheet.XGetCell(docMatrix.VisualRect.BeginRow, docMatrix.VisualRect.BeginCol);
                Excel.Range rbCell = _worksheet.XGetCell(docMatrix.VisualRect.EndRow, docMatrix.VisualRect.EndCol);
                _worksheet.Range[ltCell, rbCell].Clear();
            }
            #endregion

            #region 渲染y维度
            int aRowIndex = 0;
            for (int rowIndex = 0; rowIndex < yRows.Count; rowIndex++)
            {
                DRow dtRow = yRows[rowIndex];

                bool isVisible = true;

                foreach (var pageDim in pageDims)
                {
                    if (!string.IsNullOrEmpty(pageDim.SelectedName) && pageDim.Direction == DimensionData.DimDirection.Y)
                    {
                        string cpdName = dtRow.Items[pageDim.Index].Name;
                        if (cpdName != pageDim.SelectedName)
                        {
                            isVisible = false;
                            break;
                        }
                    }
                }

                if (isVisible)
                {
                    // 在显示的维度行记录中，添加当前维度行号
                    visualYRows.Add(rowIndex);

                    for (int dIndex = 0; dIndex < ydCount; dIndex++)
                    {
                        _worksheet.XGetCell(firstRow + aRowIndex, beginCol + dIndex).Value2 = dtRow.Items[dIndex].Name;
                        _worksheet.XGetCell(firstRow + aRowIndex, beginCol + dIndex).IndentLevel = dtRow.Items[dIndex].Level;
                        _worksheet.XGetCell(firstRow + aRowIndex, beginCol + dIndex).Interior.Color = 0xffcf9c;
                        _worksheet.XGetCell(firstRow + aRowIndex, beginCol + dIndex).Borders[Excel.XlBordersIndex.xlEdgeLeft].Weight = Excel.XlBorderWeight.xlThin;
                        _worksheet.XGetCell(firstRow + aRowIndex, beginCol + dIndex).Borders[Excel.XlBordersIndex.xlEdgeTop].Weight = Excel.XlBorderWeight.xlThin;
                        _worksheet.XGetCell(firstRow + aRowIndex, beginCol + dIndex).Borders[Excel.XlBordersIndex.xlEdgeRight].Weight = Excel.XlBorderWeight.xlThin;
                        _worksheet.XGetCell(firstRow + aRowIndex, beginCol + dIndex).Borders[Excel.XlBordersIndex.xlEdgeBottom].Weight = Excel.XlBorderWeight.xlThin;
                    }
                    aRowIndex++;
                }
            }
            #endregion

            #region 渲染x维度
            int aColIndex = 0;
            for (int rowIndex = 0; rowIndex < xRows.Count; rowIndex++)
            {
                DRow dtRow = xRows[rowIndex];

                bool isVisible = true;

                foreach (var pageDim in pageDims)
                {
                    if (pageDim.Direction == DimensionData.DimDirection.X && !string.IsNullOrEmpty(pageDim.SelectedName))
                    {
                        string cpdName = dtRow.Items[pageDim.Index].Name;
                        if (cpdName != pageDim.SelectedName)
                        {
                            isVisible = false;
                            break;
                        }
                    }
                }

                if (isVisible)
                {
                    visualXRows.Add(rowIndex);

                    for (int dIndex = 0; dIndex < xdCount; dIndex++)
                    {
                        _worksheet.XGetCell(beginRow + dIndex, firstCol + aColIndex).Value2 = dtRow.Items[dIndex].Name;

                        //sheet.XGetCell(beginRow + dIndex, firstCol + rowIndex).IndentLevel = dtRow.Items[dIndex].Level;

                        // set background
                        _worksheet.XGetCell(beginRow + dIndex, firstCol + aColIndex).Interior.Color = 0xffcf9c;

                        //set border
                        _worksheet.XGetCell(beginRow + dIndex, firstCol + aColIndex).Borders[Excel.XlBordersIndex.xlEdgeLeft].Weight = Excel.XlBorderWeight.xlThin;
                        _worksheet.XGetCell(beginRow + dIndex, firstCol + aColIndex).Borders[Excel.XlBordersIndex.xlEdgeTop].Weight = Excel.XlBorderWeight.xlThin;
                        _worksheet.XGetCell(beginRow + dIndex, firstCol + aColIndex).Borders[Excel.XlBordersIndex.xlEdgeRight].Weight = Excel.XlBorderWeight.xlThin;
                        _worksheet.XGetCell(beginRow + dIndex, firstCol + aColIndex).Borders[Excel.XlBordersIndex.xlEdgeBottom].Weight = Excel.XlBorderWeight.xlThin;
                    }
                    aColIndex++;
                }
            }
            #endregion

            #region 更新内容区域
            docMatrix.VisualRect = new ExcelDataRect();
            docMatrix.VisualRect.BeginRow = beginRow;
            docMatrix.VisualRect.EndRow = (beginRow + visualYRows.Count + xdCount);
            docMatrix.VisualRect.BeginCol = beginCol;
            docMatrix.VisualRect.EndCol = (beginCol + visualXRows.Count + ydCount);
            Debug.WriteLine("set rect:{0},{1}-{2},{3}",
                docMatrix.VisualRect.BeginRow,
                docMatrix.VisualRect.BeginCol,
                docMatrix.VisualRect.EndRow,
                docMatrix.VisualRect.EndCol);
            #endregion
        }
        */

        public static string ToAA(int value)
        {
            string AA = string.Empty;
            int d = value / 26;
            int remainder = value % 26;

            if (d == 1 && remainder == 0)
            {
                AA = ToA(26) + AA;
                d = 0;
            }
            else
            {
                AA = ToA(remainder) + AA;
            }

            while (d > 0)
            {
                remainder = d % 26;
                d = d / 26;
                AA = ToA(remainder) + AA;
            }
            return AA;
        }

        private static string ToA(int value)
        {
            if (value <= 0)
            {
                return string.Empty;
            }
            return new string((char)('A' + (value - 1)), 1);
        }
    }
}
